package com.wf.smartcomm.server.yun;

import java.io.PrintWriter;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import com.wf.smartcomm.server.bean.UnLock;
import com.wf.smartcomm.server.bean.UnitMachine;
import com.wf.smartcomm.server.client.action.BaseAction;
import com.wf.smartcomm.server.model.PushMessage;
import com.wf.smartcomm.server.push.Pusher;
import com.wf.smartcomm.server.service.UnitMachService;
import com.wf.smartcomm.server.service.UserService;
import com.wf.smartcomm.server.util.ConstantUtils;
import com.wf.smartcomm.server.util.PushUtils;
import com.wf.smartcomm.server.util.StringUtil;

@Service
@Scope("prototype")
public class DtmfCallbackAction extends BaseAction {

	private static Logger logger = Logger.getLogger(DtmfCallbackAction.class);
	
	//private static HashMap<String,HashMap<String,String>> cacheMap = new HashMap<String, HashMap<String,String>>();
	
	private static ConcurrentHashMap<String, String> confMap = new ConcurrentHashMap<String, String>();
	
	@Resource
	private UnitMachService unitServiceImpl;
	
	@Resource
	private UserService userServiceImpl;
	
	public void createCallback(){
		String callid = request.getParameter("callid");
		String confid = request.getParameter("confid");
		
		logger.info("createCallback----->"+"callid:" + callid +" confid:" + confid);
	}
	
	public void joinCallback() throws Exception{
		String callid = request.getParameter("callid");
		String confid = request.getParameter("confid");
		String number = request.getParameter("number");
		logger.info("joinCallback----->"+"callid:" + callid +" confid:" + confid+" number:"+number);
		if (StringUtils.isNotEmpty(number)) {
			if (number.length() == 16) {
				confMap.put(confid, number);
				logger.info("joinCallback-----> confMap put data: "+ number);
			}else {
				String voipAccount = confMap.get(confid);
				logger.info("joinCallback-----> voipAccount: "+ voipAccount);
				if (StringUtils.isNotEmpty(voipAccount)) {
					UnitMachine um = unitServiceImpl.getByVoip(voipAccount);
					Pusher pusher = PushUtils.getInstance();
					PushMessage pMsg = new PushMessage();
					pMsg.setPushType(ConstantUtils.PUSH_TYPE_JOIN_CONFERENCE);
					boolean result = pusher.push0x20Message(um.getPushId().getBytes(), gson.toJson(pMsg).getBytes());
					pusher.close();
					
					logger.info("joinCallback-----> join conference msg send!!! msg type:" + pMsg.getPushType());
				}else {
					logger.info("joinCallback-----> join conference msg not send because voipAccount is null!");
				}
			}
		}
	}
	
	public void quiturl() throws Exception{
		String callid = request.getParameter("callid");
		String confid = request.getParameter("confid");
		String voipAccount = confMap.get(confid);
		logger.info("leaveCallback----->"+"callid:" + callid +" confid:" + confid+" voipAccount:"+voipAccount);
		if (StringUtils.isNotEmpty(voipAccount)) {
			UnitMachine um = unitServiceImpl.getByVoip(voipAccount);
			Pusher pusher = PushUtils.getInstance();
			PushMessage pMsg = new PushMessage();
			pMsg.setPushType(ConstantUtils.PUSH_TYPE_LEAVE_CONFERENCE);
			boolean result = pusher.push0x20Message(um.getPushId().getBytes(), gson.toJson(pMsg).getBytes());
			pusher.close();
			
			if (result) {
				
				logger.info("leaveCallback-----> leave msg send success!!!");
			}else {
				logger.info("leaveCallback-----> leave msg send fail!!!");
			}
		}else {
			logger.info("leaveCallback-----> voipAccount is null!!!");
		}
		confMap.remove(confid);
	}
	
	public void pressCallback() throws Exception{
		String callid = request.getParameter("callid");
		String confid = request.getParameter("confid");
		String digits = request.getParameter("digits");
		logger.info("pressCallback----->"+"callid:" + callid +" confid:" + confid+" digits:"+digits);
		if (StringUtils.isNotEmpty(confid)) {
			String voipAccount = confMap.get(confid);
			logger.info("pressCallback-----> voipAccount: "+ voipAccount);
			if (StringUtils.isNotEmpty(voipAccount)) {
				UnitMachine um = unitServiceImpl.getByVoip(voipAccount);
				Pusher pusher = PushUtils.getInstance();
				PushMessage pMsg = new PushMessage();
				pMsg.setPushType(ConstantUtils.PUSH_TYPE_UNLOCK_MSG);
				boolean result = pusher.push0x20Message(um.getPushId().getBytes(), gson.toJson(pMsg).getBytes());
				pusher.close();
				
				if (result) {
					UnLock unlock = new UnLock();
					//unlock.setUser(user);
					unlock.setUnitMachine(um);
					unlock.setType(ConstantUtils.UNLOCK_TYPE_VOIP);
					userServiceImpl.unlock(unlock);
					logger.info("pressCallback-----> unlock success!!!");
				}else {
					logger.info("pressCallback-----> unlock fail!!!");
				}
			}else {
				logger.info("pressCallback-----> voipAccount is null!!!");
			}
		}
		
	}
	

	public void ivrService() throws Exception{
		String body = null;

		String uri = request.getRequestURI();
		//System.out.println(uri);
		// 云通讯IVR启动业务的回调请求，请求的url中固定相对地址startservice
		if (uri.contains("/startservice")) {
			body = startserver(request);
		}
		// 云通讯呼转命令的回调请求，通知第三方用户的按键超时，请求URL中的相对地址gettimeout可以自定义，demo中自定义为gettimeout
		if (uri.contains("/gettimeout")) {
			body = gettimeout(request);
		}
		// 云通讯按键命令的回调请求，通知第三方用户的按键信息，请求URL中的相对地址dtmfreport可以自定义，demo中自定义为dtmfreport
		if (uri.contains("/dtmfreport")) {
			body = dtmfreport(request);
		}
		// 云通讯IVR结束业务的回调请求，请求的url中固定相对地址stopservice
		if (uri.contains("/stopservice")) {
			body = stopservice(request);
		}
		PrintWriter out = response.getWriter();
		out.println(body);
	}
	

	// IVR启动业务，在IVR呼入或者IVR外呼后由云通讯平台发起的回调请求
	public String startserver(HttpServletRequest req) {
		// // 打印URL中的参数
		// Map map = req.getParameterMap();
		// Set<String> keySet = map.keySet();
		// for (String key : keySet) {
		// String[] values = (String[]) map.get(key);
		// for (String value : values) {
		// System.out.println(key + "=" + value);
		// }
		// }
		// 获取URL中的参数
		String appid = req.getParameter("appid");//应用id
		String callid = req.getParameter("callid");//通话id，由云通讯平台产生的一路通话的唯一标识
		String from = req.getParameter("from");//主叫号码，当IVR呼入方式为主叫的号码，当IVR外呼的方式则为空
		String to = req.getParameter("to");//被叫号码，当IVR呼入方式为IVR接入号，当IVR外呼的方式则为外呼的号码
		String direction = req.getParameter("direction");//呼叫方式，IVR呼入为0，IVR外呼为1
		//String userdata = req.getParameter("userdata");//自定义参数，只有发起当外呼请求中带有才会返回，可以通过该参数和callid绑定来确定发起的请求
		//String pushId = userdata.split("_")[0];
		//String mid = userdata.split("_")[1];
		//logger.info("startserver----->"+"pushId:"+ pushId + " mid:"+mid);
		//req.getSession().setAttribute(callid, pushId);
		//req.getSession().setAttribute("to", to);
		//req.getSession().setAttribute("mid", mid);
		// 响应包体
	    //对云通讯平台回调请求的响应包体，响应的是按键命令嵌套放音，超时没按键就放音提示用户后跳转到gettimeout
	    //命令中action='dtmfreport'为自定义按键回调相对地址
	    //numdigits='1'定义按键个数为1，当用户按任意一个键就会通知第三方服务器
	    //timeout='20'为用户按键超时时间20秒，当放音第一次完成后开始计时，用户20秒没有按键就会执行副命令
	    //loop='-1'为循环放音，当超时后停止
		String result = "<?xml version='1.0' encoding='UTF-8'?><Response><Get action='dtmfreport' numdigits='1' timeout='20'><Play loop='-1'>menu.wav</Play></Get><Play>timeout.wav</Play><Redirect>gettimeout</Redirect></Response>";
		return result;
	}

	//用户按键超时
	public String gettimeout(HttpServletRequest req){
		// 获取URL中的参数
		String appid = req.getParameter("appid");//应用id
		String callid = req.getParameter("callid");//通话id，由云通讯平台产生的一路通话的唯一标识
		//对云通讯平台回调请求的响应包体，响应的是按键命令嵌套放音，超时没按键就放音提示用户后挂断用户
		String result = "<?xml version='1.0' encoding='UTF-8' ?><Response><Get action='dtmfreport' numdigits='1' timeout='20'><Play loop='-1'>menu.wav</Play></Get><Play>timeoutbye.wav</Play><Hangup/></Response>";

		return result;
	}
	
	// 用户按键
	public String dtmfreport(HttpServletRequest req) throws Exception {
		// 获取URL中的参数
		String appid = req.getParameter("appid");//应用id
		String callid = req.getParameter("callid");//通话id，由云通讯平台产生的一路通话的唯一标识
		String digits = req.getParameter("digits");//用户按键内容
		String mid = (String) req.getSession().getAttribute("mid");
		String to = (String) req.getSession().getAttribute("to");
		String pushId = (String) req.getSession().getAttribute(callid);
		
		logger.info("dtmfreport---->"+"mid:"+mid+" to:"+to+" pushId:"+pushId);
		if (digits.equalsIgnoreCase("#")) {
			if (!StringUtil.isEmpty(pushId)) {
				Pusher pusher = PushUtils.getInstance();
				PushMessage pMsg = new PushMessage();
				pMsg.setPushType(ConstantUtils.PUSH_TYPE_UNLOCK_MSG);
				boolean result = pusher.push0x20Message(pushId.getBytes(), gson.toJson(pMsg).getBytes());
				pusher.close();
				if (result) {
					UnLock unlock = new UnLock();
					unlock.setUnitMachine(new UnitMachine(mid));
					unlock.setType(ConstantUtils.UNLOCK_TYPE_VOIP);
					unlock.setVoipNumber(to);
				}
			}else {
				logger.info("pushId is null or empty,ronglianyun cookie can not use!!!");
			}
		}
		//对云通讯平台回调请求的响应包体，响应的是放音提示后挂断用户电话
		String result = "<?xml version='1.0' encoding='UTF-8' ?><Response><Play>bye.wav</Play><Hangup/></Response>";
		
		return result;
	}

	//IVR结束业务，在用户挂机后由云通讯平台发起的回调请求
	public String stopservice(HttpServletRequest req) {
		// 获取URL中的参数
		String appid = req.getParameter("appid");//应用id
		String callid = req.getParameter("callid");//通话id，由云通讯平台产生的一路通话的唯一标识
		String starttime = req.getParameter("starttime");//主叫通话的开始时间
		String endtime = req.getParameter("endtime");//主叫通话的结束时间
		String callduration = req.getParameter("callduration");//主叫通话时长
		String sstime = req.getParameter("sstime");//被叫通话的开始时间
		String setime = req.getParameter("setime");//被叫通话的结束时间
		String seccallduration = req.getParameter("seccallduration");//被叫通话时间
		String recordurl = req.getParameter("recordurl");//录音文件下载地址
		String recordid = req.getParameter("recordid");//录音文件Id
		String errorcode = req.getParameter("errorcode");//通话中异常的错误值，可以根据错误知道出现异常的原因
		// 响应包体
		String result = "<?xml version='1.0' encoding='UTF-8' ?><Response><CmdNone/></Response>";
		return result;
	}
}
